package com.bit.cfdi.web.dao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;

import com.bit.cfdi.web.domain.Cliente;
import com.bit.cfdi.web.domain.Negocio;

public interface ClienteDAO {

	/**
	 * Saves or updates the given "Cliente" in the database
	 * @param cliente
	 * @exception
	 */
	public void save(final Cliente cliente) throws DataAccessException;

	/**
	 * retrieves all the list of "Cliente" in the database
	 * @return
	 * @exception
	 */
	public List<Cliente> getAll() throws DataAccessException;

	/**
	 * Returns a particular "Cliente" with that "nombre" and "rfc", this method
	 * will return the first "Cliente" with that characteristics
	 * @param name
	 * @param rfc
	 * @return
	 * @exception
	 */
	public Cliente getClienteByNameAndRFC(final String name, final String rfc, 
			String nombreEmpresa) throws DataAccessException;

	/**
	 * Returns a list of "Cliente" that belongs to a particular "Negocio"
	 * @param negocio
	 * @return
	 * @exception
	 */
	public List<Cliente> getAllfromNegocio(final Negocio negocio) throws DataAccessException;

	/**
	 * Returns a list that contains the Id's of the most purchased "Concepto" 
	 * for a particular "Cliente" in a period of time
	 * @param cliente
	 * @param initDate
	 * @param finalDate
	 * @return
	 * @exception
	 */
	public List<Long> getMostPurchasedItemsInTime(final Cliente cliente, 
			final Calendar initDate, final Calendar finalDate) throws DataAccessException;
	
	/**
	 * Returns the amount (of money) of total sales for a particular 
	 * "Cliente" in a period of time
	 * @param cliente
	 * @param initDate
	 * @param finalDate
	 * @return
	 * @exception
	 */
	public Map<Long, Double> getTotalSalesInTime(final Cliente cliente, 
			final Calendar initDate, final Calendar finalDate) throws DataAccessException;
	
	/**
	 * Returns the amount (of money) of total sales for a particular "Cliente"
	 * in a period of time filtering the "Comprobante" by category
	 * @param cliente
	 * @param category
	 * @param initDate
	 * @param finalDate
	 * @return
	 * @exception
	 */
	public Map<Long, Double> getTotalSalesInTimeByCategory(final Cliente cliente, 
			final String category, final Calendar initDate, 
			final Calendar finalDate) throws DataAccessException;

	/**
	 * Perform a searh in table "Cliente", it returns all the "Cliente" that
	 * at least one of the entity fields is a potencial match for the given
	 * "toSearch" string
	 * @param neg
	 * @param toSearch
	 * @return
	 * @exception
	 */
	public List<Cliente> searchCustumersByAllFields(final Negocio neg, 
			final String toSearch) throws DataAccessException;
	
	/**
	 * @exception
	 * */
	public List<Cliente> searchByRfc(String rfc) throws DataAccessException;
	
	/**
	 * Returns a particular "Cliente" with that "rfcLike", this method
	 * will return a list of "Cliente" with that characteristics
	 * @param rfcLike
	 * @return
	 * @exception
	 */
	public ArrayList<Object> getClientesByRFCLike(final String rfc, 
			final Negocio negocio) throws DataAccessException;
	
	/**
	 * Returns a particular "Cliente" with that "rfc", this method
	 * will return the first "Cliente" with that characteristics
	 * @param rfc
	 * @return
	 * @exception
	 */
	public Cliente getClienteByRFC(final String rfc) throws DataAccessException;
	
	/**
	 * Returns a particular "Cliente" with that "nombre", this method
	 * will return the first "Cliente" with that characteristics
	 * @param name
	 * @return
	 * @exception
	 */
	public Cliente getClienteByName(final String name) throws DataAccessException;
	
	/**
	 * Returns a particular "Cliente" with that "nameLike", this method
	 * will return a list of "Cliente" with that characteristics
	 * @param nameLike
	 * @return
	 * @exception
	 */
	public ArrayList<Object> getClientesByNameLike(final String name, 
			final Negocio negocio) throws DataAccessException;
	
	/**
	 * Returns the first "Cliente" with that RFC that belongs to a particular
	 * Negocio
	 * @param idNegocio
	 * @param rfc
	 * @return
	 * @exception
	 */
	public Cliente getClienteByNegocioAndRFC(final Long idNegocio, 
			final String rfc) throws DataAccessException;
	
	/**
	 * Search if a particular "Cliente" whit that "rfc" and "razon" is already
	 * store by that negocio. This because the rule is not to store two "Cliente"
	 * with the same rfc and razon.
	 * @param neg
	 * @param rfc
	 * @param razon
	 * @return
	 * @exception
	 */
	public List<Cliente> searchClienteRFCRazon(final Negocio neg, 
			final String rfc, final String razon) throws DataAccessException;
	
	public Cliente getClienteByRfcNegocio(String rfc, Negocio negocio);
	
	/**
	 * Retrieve the last inserted Cliente of a particular negocio
	 * @param negocio
	 * @return
	 * @exception
	 */
	public Cliente getLastInsertedCliente(
			final Negocio negocio) throws DataAccessException;
}
